package ufrj.safcp.tools.printing;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleJavaPrinter implements IPrinter {
	
	private static Logger logger = LoggerFactory.getLogger(SimpleJavaPrinter.class);

	private static SimpleJavaPrinter instance;

	public synchronized static SimpleJavaPrinter getInstance() {
		if (instance == null) {
			instance = new SimpleJavaPrinter();
		}
		return instance;
	}
	
	protected SimpleJavaPrinter() {
		super();
	}

	private final class ImagePrintable implements Printable {
		
		private final BufferedImage bimage;

		private ImagePrintable(BufferedImage bi) {
			this.bimage = bi;
		}

		public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
			switch (pageIndex) {
			case 0:
				printQRCode(graphics, pageFormat);
				return PAGE_EXISTS;
			default:
				return NO_SUCH_PAGE; // No other pages
			}
		}

		private void printQRCode(Graphics graphics, PageFormat pf) {
			
			// dividing the page by 2
			double realImageableHeight = pf.getImageableHeight() / 2 - pf.getImageableY();
			
			graphics.drawRect((int)pf.getImageableX(), (int)pf.getImageableY(), (int)pf.getImageableWidth(), (int)realImageableHeight);
			graphics.drawImage(this.bimage, (int)pf.getImageableX() + 15, (int)pf.getImageableY() + 15, null);
			
			
			int fontHeight = graphics.getFontMetrics().getHeight();
			String data = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date());
			char[] charArray = data.toCharArray();
			graphics.drawString(data, (int)pf.getImageableX() + (int)pf.getImageableWidth() - graphics.getFontMetrics().charsWidth(charArray, 0, charArray.length) -15 , (int)pf.getImageableY() + (int)realImageableHeight - fontHeight);
		}
	}

	public void print(final BufferedImage bi) {
		
		PrintService[] lookupPrintServices = PrinterJob.lookupPrintServices();
		
		
		List<PrintService> printServices = Arrays.asList(lookupPrintServices);
		
		logger.debug(printServices.toString());
		
		Iterator<PrintService> iterator = printServices.iterator();
		PrintService ps = null;
		while (iterator.hasNext()) {
			PrintService next = iterator.next();
			if (next.getName().contains("PDF")) {
				ps = next;
				break;
			}
		}
		if (ps == null) {
			logger.debug("Impressora PDF não encontrada.");
			return;
		}
		
		PrinterJob job;
		
		// Create an object that will hold all print parameters, such as
		// page size, printer resolution. In addition, it manages the print
		// process (job).
		job = PrinterJob.getPrinterJob();
		
		try {
			job.setPrintService(ps);
		} catch (PrinterException e1) {
			logger.error(e1.getMessage(), e1);
		}

		// setando o objeto a ser impresso, no caso este mesmo
		job.setPrintable(new ImagePrintable(bi));


		PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();

		job.getPageFormat(attributes);

		logger.debug("Atributos do ps " + ps.getName() + ": " + Arrays.asList(ps.getAttributes().toArray()));

		PrintService jobPs = job.getPrintService();

		logger.debug("Atributos do ps " + jobPs.getName() + ": " + Arrays.asList(jobPs.getAttributes().toArray()));

		logger.debug(Arrays.asList(attributes.toArray()).toString());
		try {
			job.print();
		} catch (PrinterException e) {
			logger.error(e.getMessage(), e);
		}
		
	}

}
